#ifndef KERNEL_P_H
#define KERNEL_P_H

#include <QtCore/QObject>
#include <QtCore/QSettings>
#include <QtCore/QFile>
#include <QtCore/QMutex>
#include <QtCore/QThread>
#include <QtCore/QReadWriteLock>
#include <QtSql/QSqlDatabase>
#include "logdecoder/log_decoder.h"
#include "sessionmanager/session_manager.h"
#include "mailer/mailer.h"

namespace smsrouter {

class Kernel;

class KernelPrivate : public QObject {
  Q_OBJECT
public:
  KernelPrivate();

  ~KernelPrivate();

private slots:

  void threadStarted();

  void stop();

  void firewall(SrcSubmitSm *message);

  void firewall(DestSubmitSm *message);

  void newRpcServerSession(binaryrpc::Session *session);

  void openRpcServerSession();

  void closeRpcServerSession();

  void errorRpcServerSession(const QString &error_string);

  void newMessageRpcServerSession(binaryrpc::ServerMessage *message);

  void reconnectBillingClient();

  void connectBillingClient();

  void closeBillingClient();

  void errorBillingClient(const QString &error_message);

  void doneSrcSubmitBilling(binaryrpc::ClientMessage *billing_msg,
                            const QVariant &return_value);

  void faultSrcSubmitBilling(binaryrpc::ClientMessage *billing_msg,
                             int fault_code, const QString &fault_string);

  void doneSrcDeliverBilling(binaryrpc::ClientMessage *billing_msg,
                             const QVariant &return_value);

  void faultSrcDeliverBilling(binaryrpc::ClientMessage *billing_msg,
                              int fault_code, const QString &fault_string);

  void doneDestSubmitBilling(binaryrpc::ClientMessage *billing_msg,
                             const QVariant &return_value);

  void faultDestSubmitBilling(binaryrpc::ClientMessage *billing_msg,
                              int fault_code, const QString &fault_string);

  void doneDestDeliverBilling(binaryrpc::ClientMessage *billing_msg,
                              const QVariant &return_value);

  void faultDestDeliverBilling(binaryrpc::ClientMessage *billing_msg,
                               int fault_code, const QString &fault_string);

  void send(SrcSubmitSm *message);

  void dmResponced(SrcDeliverSm *);

  void dmResponced(DestDeliverSm *);

  void mailerStateChanged(State state);

  void sessionManagerStateChanged(State state);

  void initKernelSettingsExecuted();

  void initDeliveryProfilesExecuted();

  void initRouteTableExecuted();

  void initPoolTranslatorExecuted();

  void initSrcTranslatorExecuted();

  void initSrcSessionsExecuted();

  void initDestSessionsExecuted();

  void initDeliveryErrorExecuted();

  void writeChangeKernelSettings();

signals:

  void sigStop();

private:

  PoolTranslatorRecord *getPoolTranslator(quint32 id) const;

  smslog::LogLevel getLogLevel();

  void writeChangeToDatabase();

  void transform(SrcSubmitSm *message);

  void filter(SrcSubmitSm *message);

  void filter(DestSubmitSm *message);

  bool requestBilling(SrcSubmitSm *message);

  bool requestBilling(SrcDeliverSm *message);

  bool requestBilling(DestSubmitSm *message);

  bool requestBilling(DestDeliverSm *message);

  void route(SrcSubmitSm *message);

  bool readConfig(QSettings *config);

  void checkState();

  void setState(State state);

  void initKernelSettings();

  void initDeliveryProfiles();

  void initRouteTable();

  void initPoolTranslator();

  void initSrcTranslator();

  void initSrcSessions();

  void initDestSessions();

  friend class Kernel;

  KernelSettings *settings;

  QList<DeliveryProfilesRecord *> delivery_profiles;

  QList<DeliveryErrorCodesRecord *> delivery_error_codes;

  QList<RouteTableRecord *> route_table;

  QList<PoolTranslatorRecord *> pool_translator;

  QList<SrcTranslatorRecord *> src_translator;

  QList<SrcSessionSettings *> src_sessions_settings;

  QList<DestSessionSettings *> dest_sessions_settings;

  smslog::LogLevel log_level;

  QString db_settings_host;

  int db_settings_port;

  QString db_settings_name;

  QString db_settings_uname;

  QString db_settings_pass;

  int num_connect_settings_db;

  QString db_directions_host;

  int db_directions_port;

  QString db_directions_name;

  QString db_directions_uname;

  QString db_directions_pass;

  int num_connect_directions_db;

  QString db_messages_host;

  int db_messages_port;

  QString db_messages_name;

  QString db_messages_uname;

  QString db_messages_pass;

  int num_connect_messages_db;

  QString last_error;

  SessionManager *session_manager;

  Mailer *mailer;

  dbmanager::DatabaseManager *settings_db;

  dbmanager::DatabaseManager *directions_db;

  dbmanager::DatabaseManager *messages_db;

  QHash<binaryrpc::ClientMessage *, SrcSubmitSm *> billing_src_submit;

  QHash<binaryrpc::ClientMessage *, SrcDeliverSm *> billing_src_deliver;

  QHash<binaryrpc::ClientMessage *, DestSubmitSm *> billing_dest_submit;

  QHash<binaryrpc::ClientMessage *, DestDeliverSm *> billing_dest_deliver;

  QList<binaryrpc::Session *> rpc_server_sessions;

  binaryrpc::Client *billing_client;

  binaryrpc::Server *rpc_server;

  LogDecoder *log_decoder;

  QThread *thread;

  State state;

  QReadWriteLock lock;

  QList<dbmanager::SqlQuery *> queries;
};

} // namespace smsrouter

#endif // KERNEL_P_H
